﻿#region Copyright

// AUTHOR: Terry Massey
// Copyright (c) 2011, TheShieldStore.com
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
// 
// Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
// Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation
//  and/or other materials provided with the distribution. Neither the name of the TheShieldStore.com nor the names of its contributors may be used to endorse
//  or promote products derived from this software without specific prior written permission. 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
// AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
//  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#endregion

using System.Threading;
using Microsoft.SPOT.IO;
using System;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace DisplayShield
{
    public class Program
    {
        private static readonly int MAX_X = 127, MAX_Y = 127;                   // those are the dimensions for the 144 shield, change as needed
        private static readonly DisplayShield Display = new DisplayShield();    // Start our shield class
        private static readonly Joystick Joystick = new Joystick();       // We'll be usin gthe joystick so start taht aswell
        
        private static bool noDemo = true;
        private static int bID = 1;
        private static Color eraseColor = new Color(255, 255, 255);             // white erase color

        public static void Main()
        {
            InitMenuJoystick();
            Display.SetBackgroundColor(new Color(255, 255, 255));
            Display.Clear();
            ShowMenu();

            // This show is event driven baby! 
            Thread.Sleep(Timeout.Infinite);
        }

        private static void InitMenuJoystick()
        {
            // Set  the Joystick events that we'll use
            Joystick.Up += Joystick_Up;
            Joystick.Down += Joystick_Down;
            Joystick.Push += Joystick_Push;
        }

        private static void ShowMenu()
        {
            Display.Clear();
            Thread.Sleep(15);
            Display.Print("4Display Shield Demo", new Color(128, 0, 0));

            // Print out all the demo names
            Display.Print("Ball Bounce", new Color(0, 0, 0), new Point(12, 10));
            Display.Print("Pixel Trail", new Color(0, 0, 0), new Point(12, 20));
            Display.Print("Polygons 4 Fun", new Color(0, 0, 0), new Point(12, 30));
            Display.Print("Melting Pot", new Color(0, 0, 0), new Point(12, 40));

            // Print the instructions
            Display.Print("-Use up and down to select a demo.", new Color(0, 0, 0), new Point(0, 60));
            Display.Print("-Push to run selected demo.", new Color(0, 0, 0), new Point(0, 78));

            SetArrow(); // draw the bullet for selecting demos
        }

        private static void ballBounce()
        {
            while (Joystick.JoyStickValue(4))
            {
                // waiting for the user to let go of the joystick
            }

            Color ballColor = new Color(0, 255, 0);

            Display.Clear();

            Random r = new Random();
            int xd = 0;
            int yd = 0;

            int x = MAX_X / 2, y = MAX_Y / 2; // set the startlocation of the ball to the center of the screen

            // Make sure that the ball doesnt bounce side to side
            while(xd == 0)
                xd = r.Next(10) - 5;
            // Make sure that the ball doesnt bounce up and down
            while (yd == 0)
                yd = r.Next(10) - 5;

            while (!Joystick.JoyStickValue(4))                          // While the joystick push isnt pressed
            {
                Display.DrawCircle(new Point(x, y), 4, ballColor);      // draw the ball at the new location
                Thread.Sleep(40);                                       // hold on a sec, our eyes need to see it !

                if (x + 4 > MAX_X || x < 4)
                    xd = -xd;                                           // The ball hit the left or right of the screen, reverse x direction

                if (y + 4 > MAX_Y || y < 4)
                    yd = -yd;                                           // The ball hit the top or bottom of the screen, reverse y direction

                Display.DrawCircle(new Point(x, y), 4, eraseColor);     // draw a white ball in the same location to erase the ball

                // update the ball's location
                x += xd;
                y += yd;
            }
        }

        private static void pixelTrail()
        {
            while (Joystick.JoyStickValue(4))
            {
                // waiting for the user to let go of the joystick
            }

            Color trailColor = new Color(255, 0, 0);

            Display.Clear();

            Random r = new Random();
            int xd = 0;
            int yd = 0;

            Point start = new Point(MAX_X / 2, MAX_Y / 2), end = new Point(MAX_X / 2, MAX_Y / 2);

            // Make sure that the laser doesnt bounce side to side
            while (xd == 0)
                xd = r.Next(10) - 5;
            // Make sure that the laser doesnt bounce up and down
            while (yd == 0)
                yd = r.Next(10) - 5;

            while (!Joystick.JoyStickValue(4))
            {
                if (end.X > 123 || end.X < 4)
                    xd = -xd;

                if (end.Y > 123 || end.Y < 4)
                    yd = -yd;

                // offset the front end on the laser
                end.X += xd;
                end.Y += yd;

                Display.DrawLine(start, end, trailColor);
                start = end; // now that is the old location, i.e. the back end

                Thread.Sleep(40);
            }
        }

        private static void polygons4Fun()
        {
            while (Joystick.JoyStickValue(4))
            {
                // waiting for the user to let go of the joystick
            }

            Display.Clear();

            Point[] octPoints = new Point[3];
            Random r = new Random();
            Color polyColor = new Color(0, 0, 255);
            int wait = 50; // sleep time starts at 50 millisecs

            while (!Joystick.JoyStickValue(4))
            {
                Display.DrawPolygon(octPoints, eraseColor);                             // erase the old polygon
                
                for (int i = 0; i < 3; i++)
                    octPoints[i] = new Point(r.Next(127), r.Next(127));                 // set all 3 points to a random location

                Display.DrawPolygon(octPoints, polyColor);                              // Draw the polygon
                Display.DrawRectangle(new Point(0, 0), new Point(127, 9), eraseColor);  // erase the top of the screen using a rectangle
                Display.Print("Wait: " + wait, polyColor);                              // to allow this text to be printed without overlap.

                Thread.Sleep(wait);                                                     // sleep for amount set by user

                if (Joystick.JoyStickValue(1))              // if left is pressed
                {
                    if (wait > 0)                           // lets not go into negative waiting (sorry this shield does not support time travel)
                        wait--;                             // decrease the waiting time by one
                    while (Joystick.JoyStickValue(1)) { }   // wait for user to let go of the joystick
                }
                else if (Joystick.JoyStickValue(3))         // if right is pressed
                {
                    wait++;
                    while (Joystick.JoyStickValue(3)) { }
                }
            }

        }

        private static void meltingPot()
        {
            Random r = new Random();
            Point start = new Point(r.Next(127), r.Next(127));
            Point end = new Point(r.Next(127), r.Next(127));
            Point center = new Point(64, 64);
            Color ballColor = new Color(255, 255, 0);
            Color polyColor = new Color(255, 0, 0);

            int sxd = 0;
            int syd = 0;
            int exd = 0;
            int eyd = 0;

            // Make sure that the ball doesnt bounce side to side
            while (sxd == 0)
                sxd = r.Next(10) - 5;
            // Make sure that the ball doesnt bounce up and down
            while (syd == 0)
                syd = r.Next(10) - 5;

            // Make sure that the ball doesnt bounce side to side
            while (exd == 0)
                exd = r.Next(10) - 5;
            // Make sure that the ball doesnt bounce up and down
            while (eyd == 0)
                eyd = r.Next(10) - 5;

            while (Joystick.JoyStickValue(4))
            {
                // waiting for the user to let go of the joystick
            }
            
            Display.Clear();
            Display.Print("MELTING POT ROCKS", new Color(100, 23, 90), new Point(0, 0));

            // draw five rectangles at random locations in random colors
            for (int i = 0; i < 5; i++)
                Display.DrawRectangle(new Point(r.Next(127), r.Next(127)), new Point(r.Next(127), r.Next(127)), new Color(r.Next(255), r.Next(255), r.Next(255)));
           
            // draw five hundred pixels at random locations in random colors
            for (int i = 0; i < 500; i++)
                Display.DrawPixel(new Point(r.Next(127), r.Next(127)), new Color(r.Next(255), r.Next(255), r.Next(255)));

            // this code follows the same logic behind the ball bounce but it has two balls
            // it also draws a polygon using the the center of the screen, one ball's location, and the other ball's location, as points.
            while (!Joystick.JoyStickValue(4))
            {
                Display.DrawCircle(start, 4, ballColor);
                Display.DrawCircle(end, 4, ballColor);
                Display.DrawPolygon(new Point[] { start, center, end }, polyColor);

                Thread.Sleep(40);

                if (start.X + 4 > MAX_X || start.X < 4)
                    sxd = -sxd;

                if (start.Y + 4 > MAX_Y || start.Y < 4)
                    syd = -syd;

                if (end.X + 4 > MAX_X || end.X < 4)
                    exd = -exd;

                if (end.Y + 4 > MAX_Y || end.Y < 4)
                    eyd = -eyd;

                Display.DrawCircle(start, 4, eraseColor);
                Display.DrawCircle(end, 4, eraseColor);
                Display.DrawPolygon(new Point[] { start, center, end }, eraseColor);

                start.X += sxd;
                start.Y += syd;
                end.X += exd;
                end.Y += eyd;
            }

        }

        private static void SetArrow(int i = 1)
        {
            Display.DrawCircle(new Point(6, 10 * bID + 3), 4, eraseColor);    // draw the bullet in white to earase it
            bID = i;                                                          // set the id of the bullet location.
            Display.DrawCircle(new Point(6, 10 * bID + 3), 4, new Color(0, 0, 255));          // draw the bullet at the new location
            bID = i;                                                    
        }

        private static void Joystick_Push(object sender, JoystickEventArgs args)
        {
            if (noDemo) // we are in the menu
            {
                // show a demo depending on where the ball is
                if (bID == 1)
                    ballBounce();
                else if (bID == 2)
                    pixelTrail();
                else if (bID == 3)
                    polygons4Fun();
                else if (bID == 4)
                    meltingPot();
            }
            else
                ShowMenu(); // demo is running, show the menu

            noDemo = !noDemo; // toggle this bool
        }
        
        private static void Joystick_Down(object sender, JoystickEventArgs args)
        {
            if (noDemo)
                if (bID < 4)
                    SetArrow(bID + 1);
        }

        private static void Joystick_Up(object sender, JoystickEventArgs args)
        {
            if (noDemo)
                if (bID > 1)
                    SetArrow(bID - 1);
        }
    }
}